;;; ----------------------------------------------------------------------
;;; Simple VIC20 serial program downloader
;;; Copyright 2013 Chris Baird,, <cjb@brushtail.apana.org.au>
;;; Distributed to the GPLV3 terms and conditions.
;;; ---
;;; Due to an issue in the VIC20's Kernal, it can't currently save the
;;; $A000-$BFFF cartridge bank to tape.
;;; --
;;; build with cc65's ca65 thusly:
;;;    $ ca65 -l downloader.asm && ld65 -t none downloader.o
;;; --
;;; [$Id: downloader.asm,v 1.2 2014/06/03 15:34:24 cjb Exp cjb $]
;;; ----------------------------------------------------------------------

	OPEN	= $FFC0
	CHKIN	= $FFC6
	CHKOUT	= $FFC9
	CHROUT	= $FFD2
	CHRIN	= $FFCF
	SETNAM	= $FFBD
	SETLFS 	= $FFBA
	CLOSE  	= $FFC3
	CLALL	= $FFE7
	CLRCHN	= $FFCC
	READST	= $FFB7

	pointer	= 251
	buffer 	= 7724
	bufferptr = 253

.define savecode 0
.define basicloader 0

;;; ----------------------------------------------------------------------
;;; ----------------------------------------------------------------------

.if basicloader
	.org 4097
	.byte 11,16, 1,0, 158,"4109", 0,0,0
.else
	.org 40960
.endif

;;;

.if savecode
	jmp downloader
	jmp savearea
.endif


;;; ----------------------------------------------------------------------

downloader:
	lda #<buffer
	sta bufferptr
	lda #>buffer
	sta bufferptr+1

	ldy #0
dl1:	lda banner,y
	jsr CHROUT
	iny
	cmp #0
	bne dl1

	;; open RS232 channel @1200 8N1
	;; open 2,2,3,chr$(8)+chr$(0)

	lda #2
	ldx #<controlstring
	ldy #>controlstring
	jsr SETNAM

	lda #2
	ldx #2
	ldy #3
	jsr SETLFS

	jsr OPEN

	ldx #2
	jsr CHKIN
	ldx #2
	jsr CHKOUT
	jsr CHRIN		;activate the channel (apparently)

;;;

mainloop:
	ldy #0
cl1:	lda #0
	sta buffer+30720,y
	sta 8185-255+30720,y
	lda #32
	sta buffer,y
	sta 8185-255,y
	iny
	bne cl1

pll1:	lda linetxt,y		;print# line
	jsr CHROUT
	iny
	cpy #5			;includes invisible M/13 character
	bne pll1

;;;

	ldy #0
waitchar:
	jsr CHRIN
	cmp #0
	beq waitchar
	cmp #13
	beq parseline
	cmp #32
	beq okaychar
	cmp #'9'+1
	bcs mainloop
	cmp #'0'
	bcc mainloop

okaychar:
	sta buffer,y
	iny
	bne waitchar

;;;

parseline:
	cpy #7
	bcc mainloop		;too short?
	lda #0
	sta buffer,y		;note the EOL
	sta checksum
	sta rawindex

	ldx #5			;parse the destination address
	tay
	jsr text2bin
	sta pointer
	lda result+1
	sta pointer+1

	cmp #255		;address "65535" EOF flag
	bne parsenum
	cmp result+1
	bne parsenum
	jsr CLALL		;exit program
	jmp CLRCHN

;;;

	;ldy #5			;was incremented by the previous text2bin
	;sty bufferindex
parsenum:
	;ldy bufferindex
	lda buffer,y
	beq parsecomplete
	ldx #3
	jsr text2bin
	;sty bufferindex
	;lda result
	ldx rawindex
	sta rawbuffer,x

	clc
	adc checksum
	sta checksum

	;inc bufferindex	;text2bin took care of this
	;inc bufferindex
	;inc bufferindex
	inc rawindex
	bne parsenum

;;;

parsecomplete:
	sec			;because the cksum got included as well
	lda checksum
	sbc result
	cmp result
	bne continue

pokein:	ldy rawindex
	bne pokel2		;skip the checksum value
pokel1:	lda rawbuffer,y
	sta (pointer),y
pokel2:	dey
	bpl pokel1		;can't do more than 128 bytes per line

;;; increase line counter

	ldy #3
incdec:	clc
	lda linetxt,y
	adc #1
	sta linetxt,y
	cmp #'9'+1
	bcc continue
	lda #'0'
	sta linetxt,y
	dey
	bpl incdec

continue:
	jmp mainloop


;;; ----------------------------------------------------------------------
;;; ----------------------------------------------------------------------

banner:
	.byte 147, 31, "RX LINE: ", 144, "0000"
	.byte 144, "M"		;hidden CR
	.byte 13, 28, "----------------------", 144, 0

	linetxt 	= 7689
	rawbuffer 	= 8164-66

;;; control register byte
	BAUD50 		= 1
	BAUD110 	= 3
	BAUD300 	= 6
	BAUD1200 	= 8
	BAUD2400 	= 10
	WORD8 		= 0
	WORD7 		= 32
	ONESTOPBIT 	= 0
;;; command register byte
	THREEWIRE 	= 0
	FLOWCONTROL 	= 1
	FULLDUPLEX 	= 0
	HALFDUPLEX 	= 16
	NOPARITY 	= 0
	ODDPARITY 	= 32
	EVENPARITY 	= 96

controlstring:
	.byte BAUD1200+WORD8+ONESTOPBIT, THREEWIRE+FULLDUPLEX+NOPARITY

bufferindex:
	.byte 0

rawindex:
	.byte 0

checksum:
	.byte 0

;;; ----------------------------------------------------------------------
;;; routine: text2bin
;;; .X = number of digits to convert (either 3 or 5)
;;; .Y = start of digits in buffer
;;; returns result_lo in .A
;;; buffer index in .Y updated to 'next value'

result:	.word 0

text2bin:
	lda #0
	sta result
	sta result+1

t2bloop:
	lda (bufferptr),y
	sec
	sbc #48
	cmp #10
	bcs nextdigit		;it was a space

	pha

	;; multiply result by 10 first

	asl result		; multiply result by 2, remember
	rol result+1
	lda result+1
	pha
	lda result
	pha

	asl result		; multiply by another 4
	rol result+1
	asl result
	rol result+1

	pla			; add x2 and x8
	adc result
	sta result
	pla
	adc result+1
	sta result+1

	;; now can add new digit

	pla
	adc result
	sta result
	lda result+1
	adc #0
	sta result+1

	;

nextdigit:
	iny
	dex
	bne t2bloop
	lda result
	rts


;;; ----------------------------------------------------------------------
;;; ----------------------------------------------------------------------
.if savecode

;;; TODO: provide a way to change the start and end locations..

savearea:
	SCREEN = 7680
	INPBUF = $0200
	EOLINP = $C8
	savestart = 172		;some docs infer this is hardcoded?
	SAVE   = $FFD8

	; clear screen
	; draw filename area

	ldy #0
savel1:	lda prompt,y
	beq getname
	jsr CHROUT
	iny
	bne savel1

	ldy #21
savel2:	lda #96
	sta 7680+22,y
	lda #0
	sta 38400+22,y
	dey
	bpl savel2

	; input screen editor
getname:
	ldx #0
gnl1:	jsr CHRIN
	cmp #13
	bne gnl1
	jsr CHROUT
	jsr CHROUT
	jsr CHROUT
	jsr CHROUT
	jsr CHROUT

	;; parse the start and ending locations from the screen

	lda #<starttext
	sta bufferptr
	lda #>starttext
	sta bufferptr+1

	ldy #0
	ldx #5
	jsr text2bin
	sta savestart
	lda result+1
	sta savestart+1

	ldy #(endtext-starttext)
	ldx #5
	jsr text2bin

	;; get the filename and its length from the screen
	;; munge the screen filename text into petscii

	ldx #0
gnl2:	lda 7680+22,x
	cmp #96
	beq gnb2
	cmp #32
	bcs gnb1
	ora #64
gnb1:	sta 7680+22,x
	inx
	cpx #22
	bne gnl2

gnb2:	txa
	ldx #<(7680+22)
	ldy #>(7680+22)
	jsr SETNAM

	;;

	lda #1
	ldx #1
	ldy #3
	jsr SETLFS

	lda #savestart
	ldx result
	ldy result+1
	jmp SAVE

prompt:	.byte 144,147,"FILENAME",13,13,13
	starttext = 7680 + 66 + 7
	endtext = starttext + 22
	.byte "START: 40960",13
	.byte "END  : 49151",19,17,0
.endif


;;; ----------------------------------------------------------------------
